#include "avro/basics.h"
#include "avro_napi.h"
#include <cstddef>
#include <cstdint>
#include <sys/param.h>

// 从二进制缓冲区中读取变长整数（variable-length integer），并进行解码（符合 Avro 等序列化协议中对整数 / 长整数的编码规范）
long OhosAvroC::ReadLong(uint8_t* uData) {
    if (uData == nullptr) {
        return OHOS_AVRO_ERR_NO;
    }
    long n = 0; // 用于存储解码过程中的整数（前28位用整数处理）
    long k = 0; // 记录当前已处理的位数（每次累加7，因为每个字节贡献7位有效数据）
    uint8_t* buf = uData; // 实例关联的二进制缓冲区
    long b, h, f, fk; // 临时变量：b=当前字节，h=延续标志，f=浮点数（处理长整数），fk=浮点数计算的权重
    long pos = 0;
    
    do {
        b = buf[pos++];  // 读取当前位置的字节，并将指针后移一位
        h = b & 0x80;         // 提取最高位（0x80 = 10000000b），判断是否还有后续字节（h≠0则继续）
        n |= (b & 0x7f) << k; // 提取低7位有效数据（b&0x7f），左移k位后合并到n中
        k += 7;               // 累加已处理的位数（每次7位）
    } while (h && k < 28);  // 循环条件：有后续字节（h≠0）且未超过28位（4×7）
    
    if (h) {  // 如果h≠0，说明还有更多字节（超过28位）
      // 切换到浮点数运算，避免整数溢出
      f = n;               // 用浮点数f承接之前的28位数据
      fk = 268435456;      // 2^28（后续字节的权重起点）
      do {
        b = buf[pos++];  // 继续读取下一个字节
        f += (b & 0x7f) * fk; // 低7位数据 × 当前权重，累加到f中
        fk *= 128;            // 权重×128（即×2^7，因为每个字节贡献7位）
      } while (b & 0x80);     // 直到某字节最高位为0（无后续字节）
    
      // ZigZag解码：将无符号浮点数转换为有符号整数
      return (f % 2 ? -(f + 1) : f) / 2;
    }
    
    return (n >> 1) ^ -(n & 1);
}

int OhosAvroC::MatchLong(const uint8_t* buffer_data, int buffer_len, const uint8_t* buffer_data2, int buffer_len2) {
    long n1 = ReadLong((uint8_t*)buffer_data);
    long n2 = ReadLong((uint8_t*)buffer_data2);
    if (n1 == OHOS_AVRO_ERR_NO || n2 == OHOS_AVRO_ERR_NO) {
        return OHOS_AVRO_ERR_NO;
    }
    return n1 == n2 ? 0 : (n1 < n2 ? -1 : 1);
}

// 跨平台：按小端序解析 4 个字节为 float
float OhosAvroC::readFloatLE(const uint8_t* bytes) {
    // 小端序：低地址存储低字节，高地址存储高字节
    // 重组 4 个字节为 32 位无符号整数（小端序）
    uint32_t bits = 
        (static_cast<uint32_t>(bytes[0]) << 0)  // 第 0 字节（最低位）
        | (static_cast<uint32_t>(bytes[1]) << 8) // 第 1 字节
        | (static_cast<uint32_t>(bytes[2]) << 16)// 第 2 字节
        | (static_cast<uint32_t>(bytes[3]) << 24);// 第 3 字节（最高位）
    
    // 将 32 位整数的内存映射为 float（通过联合体避免严格别名问题）
    union {
        uint32_t u;
        float f;
    } converter;
    converter.u = bits;
    return converter.f;
}

float OhosAvroC::ReadFloat(uint8_t* buf, int len) {
    int pos = 0;
    pos += 4;
    if (pos > len) {
        return OHOS_AVRO_ERR_NO;
    }
    return readFloatLE(buf);
}

int OhosAvroC::MatchFloat(const uint8_t* buffer_data, int buffer_len, const uint8_t* buffer_data2, int buffer_len2) {
    float n1 = ReadFloat((uint8_t*)buffer_data, buffer_len);
    float n2 = ReadFloat((uint8_t*)buffer_data2, buffer_len2);
    if (n1 == OHOS_AVRO_ERR_NO || n2 == OHOS_AVRO_ERR_NO) {
        return OHOS_AVRO_ERR_NO;
    }
    // 浮点数==比较会有问题
    return n1 == n2 ? 0 : (n1 < n2 ? -1 : 1);
}

// 从字节数组（小端序）读取 64 位双精度浮点数（double）
double OhosAvroC::readDoubleLE(const uint8_t* bytes) {
    // 步骤 1：按小端序重组 8 个字节为 64 位无符号整数
    // 小端序规则：低地址字节对应低阶位，高地址字节对应高阶位
    uint64_t bits = 
        (static_cast<uint64_t>(bytes[0]) << 0)   // 第 0 字节（最低 8 位）
        | (static_cast<uint64_t>(bytes[1]) << 8)  // 第 1 字节（8-15 位）
        | (static_cast<uint64_t>(bytes[2]) << 16) // 第 2 字节（16-23 位）
        | (static_cast<uint64_t>(bytes[3]) << 24) // 第 3 字节（24-31 位）
        | (static_cast<uint64_t>(bytes[4]) << 32) // 第 4 字节（32-39 位）
        | (static_cast<uint64_t>(bytes[5]) << 40) // 第 5 字节（40-47 位）
        | (static_cast<uint64_t>(bytes[6]) << 48) // 第 6 字节（48-55 位）
        | (static_cast<uint64_t>(bytes[7]) << 56); // 第 7 字节（56-63 位，最高位）
    
    // 步骤 2：将 64 位整数的二进制位直接映射为 double（通过联合体避免类型转换问题）
    union {
        uint64_t u;  // 64 位无符号整数（用于承载字节重组结果）
        double d;    // 64 位双精度浮点数（共享内存，直接映射二进制位）
    } converter;
    
    converter.u = bits;
    return converter.d;
}


double OhosAvroC::ReadDouble(uint8_t* buf, int len) {
    int pos = 0;
    pos += 8;
    if (pos > len) {
        return OHOS_AVRO_ERR_NO;
    }
    return readDoubleLE(buf);
}

int OhosAvroC::MatchDouble(const uint8_t* buffer_data, int buffer_len, const uint8_t* buffer_data2, int buffer_len2) {
    double n1 = ReadDouble((uint8_t*)buffer_data, buffer_len);
    double n2 = ReadDouble((uint8_t*)buffer_data2, buffer_len2);
    if (n1 == OHOS_AVRO_ERR_NO || n2 == OHOS_AVRO_ERR_NO) {
        return OHOS_AVRO_ERR_NO;
    }
    // 浮点数==比较会有问题
    return n1 == n2 ? 0 : (n1 < n2 ? -1 : 1);
}
// 消息头长度目前按照2计算，真是情况不固定，这里可能有问题
int OhosAvroC::MatchUnion(const uint8_t* buffer_data, int buffer_len, const uint8_t* buffer_data2, int buffer_len2, avro_schema_t schema) {
    int index = ((uint8_t*)buffer_data)[0] / 2; // 当前索引
    avro_schema_t branch = avro_schema_union_branch(schema, index);
    
    int index2 = ((uint8_t*)buffer_data2)[0] / 2; // 当前索引
    if (index != index2) { // 两个union的数据不是一个具体类型
        return OHOS_AVRO_ERR_NO;
    }
    
    long n1 = ReadLong((uint8_t*)buffer_data);
    long n2 = ReadLong((uint8_t*)buffer_data2);
    if (n1 == n2) {
        return Compare_Buffers((const uint8_t*)buffer_data+2, buffer_len-2, 
            (const uint8_t*)buffer_data2+2, buffer_len2-2, branch); // 2是消息头长度，不固定，这里可能有问题
    } else {
        return n1 < n2 ? -1 : 1;
    }
}

// 未完成，不知道每个字段序列化后的数据长度，不好处理下个数据
int OhosAvroC::MatchRecord(const uint8_t* buffer_data, int buffer_len, const uint8_t* buffer_data2, int buffer_len2, 
    avro_schema_t schema) {
    
    size_t size = avro_schema_record_size(schema);
    for (int i = 0; i < size; i++) {
        avro_schema_t Valschema = avro_schema_record_field_get_by_index(schema, i);
        // 。。。不知道每个字段序列化后的数据长度，不好处理下个数据
        return Compare_Buffers((const uint8_t*)buffer_data, buffer_len, 
            (const uint8_t*)buffer_data2, buffer_len2, Valschema);
    }
    return buffer_len - buffer_len2;
}

int OhosAvroC::MatchString(const uint8_t* buffer_data, int buffer_len, const uint8_t* buffer_data2, int buffer_len2) {
    // 获取长度
    long n1 = ReadLong((uint8_t*)buffer_data);
    long n2 = ReadLong((uint8_t*)buffer_data2);
 
    int len = MIN(n1, n2);
    for (int i = 0; i < len; i++) {
        long res = ((uint8_t*)buffer_data)[i] - ((uint8_t*)buffer_data2)[i];
        if (res == 0) {
            continue;
        }
        return res;
    }
    
    return n1 - n2;
}

int OhosAvroC::Compare_Buffers(const uint8_t* buffer_data, int buffer_len, const uint8_t* buffer_data2, int buffer_len2, 
    avro_schema_t schema) {
    switch (schema->type) {
    case AVRO_INT32:
    case AVRO_INT64:
    case AVRO_ENUM:
        return MatchLong(buffer_data,buffer_len, buffer_data2, buffer_len2);
    case AVRO_FLOAT:
        return MatchFloat(buffer_data,buffer_len, buffer_data2, buffer_len2);
    case AVRO_DOUBLE:
        return MatchDouble(buffer_data,buffer_len, buffer_data2, buffer_len2);
    case AVRO_BOOLEAN:
        return ((uint8_t*)buffer_data)[0] - ((uint8_t*)buffer_data2)[0];
    case AVRO_ARRAY: // 未完成，不知道每个字段序列化后的数据长度，不好处理下个数据
        return MatchArray(buffer_data,buffer_len, buffer_data2, buffer_len2, schema);
    case AVRO_MAP:
        return OHOS_AVRO_ERR_NO; // 不支持map比较，js也不支持
    case AVRO_RECORD: // 未完成，不知道每个字段序列化后的数据长度，不好处理下个数据
        return MatchRecord(buffer_data,buffer_len, buffer_data2, buffer_len2, schema); 
    case AVRO_UNION: // 消息头长度目前按照2计算，真是情况不固定，这里可能有问题
        return MatchUnion(buffer_data,buffer_len, buffer_data2, buffer_len2, schema); 
    case AVRO_STRING:
    case AVRO_BYTES:
        return MatchString(buffer_data,buffer_len, buffer_data2, buffer_len2);
    case AVRO_FIXED:
        return MatchFixed(buffer_data, buffer_len, buffer_data2, buffer_len2);
    default:
        return OHOS_AVRO_ERR_NO;
    }
    
    return OHOS_AVRO_ERR_NO;
}

// 未完成，不知道每个字段序列化后的数据长度，不好处理下个数据
int OhosAvroC::MatchArray(const uint8_t* buffer_data, int buffer_len, const uint8_t* buffer_data2, int buffer_len2, avro_schema_t schema) {
    // 获取长度
    long n1 = ReadLong((uint8_t*)buffer_data);
    long n2 = ReadLong((uint8_t*)buffer_data2);
 
    size_t elementCount1 = buffer_data[0]/2;
    size_t elementCount2 = buffer_data2[0]/2;
    avro_schema_t valSchema = avro_schema_map_values(schema);

    // ...
    return n1 - n2;
}

int OhosAvroC::MatchFixed(const uint8_t* buffer_data, int buffer_len, const uint8_t* buffer_data2, int buffer_len2) {
    for (int i = 0; i < buffer_len; i++) {
        int res = ((uint8_t*)buffer_data)[i] - ((uint8_t*)buffer_data2)[i];
        if (res == 0) {
            continue;
        }
        return res;
    }
    
    return buffer_len - buffer_len2;
}

napi_value OhosAvroC::CompareBuffers(napi_env env, napi_callback_info info) {
    napi_value result;
    size_t argc = 2;
    napi_value args[2];
    napi_value jsthis;
    napi_status status = napi_get_cb_info(env, info, &argc, args, &jsthis, nullptr);
    if (status != napi_ok || argc < 1) {
        LOGERROR("Get cb failed！");
        return nullptr;
    }
    
    OhosAvroC *obj;
    status = napi_unwrap(env, jsthis, (void **)&obj);
    if (status != napi_ok) {
        LOGERROR("Failed to napi_unwrap");
        return nullptr;
    }

    int res = OHOS_AVRO_ERR_NO;
    void *buffer_data;
    size_t buffer_len = 0;
    status = napi_get_arraybuffer_info(env, args[0], &buffer_data, &buffer_len);
    if (status != napi_ok) {
        LOGERROR("Get buffer info failed！");
        return nullptr;
    }

    void *buffer_data2;
    size_t buffer_len2 = 0;
    status = napi_get_arraybuffer_info(env, args[1], &buffer_data2, &buffer_len2);
    if (status != napi_ok) {
        LOGERROR("Get buffer info failed！");
        return nullptr;
    }
    res = Compare_Buffers((const uint8_t*)buffer_data, buffer_len, (const uint8_t*)buffer_data2, buffer_len2, obj->schema_);
    if (res == OHOS_AVRO_ERR_NO) {
        LOGERROR("Failed to compare buffer!");
        return nullptr;
    }

    status = napi_create_int32(env, res, &result);
    if (status != napi_ok) {
        LOGERROR("Failed to create boolean!");
        return nullptr;
    }

    return result;
}